package com.atguigu.exam.service.impl;


import com.atguigu.exam.entity.Category;
import com.atguigu.exam.entity.Question;
import com.atguigu.exam.mapper.CategoryMapper;
import com.atguigu.exam.mapper.QuestionMapper;
import com.atguigu.exam.service.CategoryService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;


@Slf4j
@Service
public class CategoryServiceImpl extends ServiceImpl<CategoryMapper, Category> implements CategoryService {
    @Autowired
    private QuestionMapper questionMapper;

    /**
     * 获取分类列表（包含题目数量）
     *
     * @return
     */
    @Override
    public List<Category> getCategories() {
        //1.查询所有分类信息
        List<Category> list = list();
        //2.查询题目表，所有分类的总数量
        fillCategoryCount(list);
        //返回结果
        return list;
    }

    /**
     * 获取分类树形结构
     *
     * @return
     */
    @Override
    public List<Category> getCategoryTree() {
        //1.查询所有分类信息
        List<Category> list = list();
        //2.查询题目表，所有分类的总数量
        fillCategoryCount(list);
        //3.针对list根据parentId进行分类
        Map<Long, List<Category>> parentIdMap = list.stream().collect(Collectors.groupingBy(Category::getParentId));
        //4.过滤出父类集合(父类的父类id为0)
        List<Category> parentList = list.stream().
                filter(category -> category.getParentId() == 0).collect(Collectors.toList());
        //5.为父类的children赋值
        parentList.forEach(category -> {
            List<Category> childrenList = parentIdMap.getOrDefault(category.getId(), new ArrayList<>());
            childrenList.sort((Comparator.comparingInt(Category::getSort)));
            //设置children
            category.setChildren(childrenList);
            //获取子类所有的count之和
            long ChildrenCountSum = parentIdMap.get(category.getId()).stream().mapToLong(Category::getCount).sum();
            //设置count
            category.setCount(category.getCount() + ChildrenCountSum);
        });

        //返回结果
        return parentList;
    }

    /**
     * 添加分类
     * @param category
     */
    @Override
    public void addCategory(Category category) {
        //判断该父类下是否存在同名的子分类
        LambdaQueryWrapper<Category> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(Category::getName, category.getName());
        //在该service下获取其对应的mapper
        CategoryMapper categoryMapper = getBaseMapper();
        //调用exists方法进行判断
        boolean exists = categoryMapper.exists(lambdaQueryWrapper);
        if (exists) {
            Category parent = getById(category.getParentId());
            throw new RuntimeException("添加分类失败,在%s父类下已存在相同名称的子分类".formatted(parent.getName()));
        }
        //添加成功
        save(category);
    }

    /**
     * 更新分类信息
     *
     * @param category
     */
    @Override
    public void updateCategory(Category category) {
        //判断更新是否与该父类下其他的子分类名称相同
        LambdaQueryWrapper<Category> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        //不同id
        lambdaQueryWrapper.ne(Category::getId, category.getId());
        //相同名称
        lambdaQueryWrapper.eq(Category::getName, category.getName());
        boolean exists = getBaseMapper().exists(lambdaQueryWrapper);
        if (exists) {
            throw new RuntimeException("更新分类信息失败,修改后的名称与同父类下子类名称相同");
        }
        //更新信息
        updateById(category);
    }

    /**
     * 删除分类
     *
     * @param id
     */
    @Override
    public void deleteCategory(Long id) {
        //父分类不允许被删除
        Category category = getById(id);
        if (category.getParentId() == 0) {
            throw new RuntimeException("删除失败,父类不允许被删除");
        }
        //判断该分类下是否有题目
        LambdaQueryWrapper<Question> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(Question::getCategoryId, id);
        Long count = questionMapper.selectCount(lambdaQueryWrapper);
        if (count > 0) {
            throw new RuntimeException("删除失败,该分类下有%s道题".formatted(count));
        }
        //删除
        removeById(id);
    }

    /**
     * 查询题目表，所有分类对应题目的总数量
     * @param list
     */
    private void fillCategoryCount(List<Category> list) {
        //判断list是否为空
        if (list == null || list.isEmpty()) {
            throw new RuntimeException("查询的分类集合为空");
        }
        //查询所有分类和分类对应的题目数量
        List<Map<Long, Long>> mapList = questionMapper.selectCategoryAndCount();
        //转换为map形式
        Map<Long, Long> map = mapList.stream().collect(Collectors.toMap(m -> m.get("category_id"), m -> m.get("ct")));
        //为每个分类查询count并赋值
        list.forEach(category -> category.setCount(map.getOrDefault(category.getId(), 0L)));

    }
}